from django.views import View
from django.http import HttpResponse,JsonResponse
from django_redis import get_redis_connection
from ihome.libs.captcha.captcha import captcha
from ihome.libs.yuntongxun.ccp_sms import CCP
from celery_tasks.sms.tasks import ccp_send_sms_code
from wangziye.models import User
from django.contrib.auth import login
import logging,random,json,re
logger = logging.getLogger('django')
# 图形验证码视图
class ImageCodeView(View):
    def get(self, request):
        # 生成图形验证码, 保存到redis中, 另外返回图片
        cur = request.GET.get('cur')

        # 1.调用工具类 captcha 生成图形验证码
        text, image = captcha.generate_captcha()

        # 2.链接 redis, 获取链接对象
        redis_conn = get_redis_connection('verify_code')

        # 3.利用链接对象, 保存数据到 redis, 使用 setex 函数
        # redis_conn.setex('<key>', '<expire>', '<value>')
        redis_conn.setex('img_%s' % cur, 300, text)

        # 4.返回(图片)
        return HttpResponse(image, content_type='image/jpg')

# 短信验证码视图
class SMScodeView(View):
    def post(self, request):
        # 1. 接收参数
        dict = json.loads(request.body.decode())
        mobile = dict.get('mobile')
        text = dict.get('text')
        id = dict.get('id')

        # 1.1 避免短信验证码重复发送
        redis_conn = get_redis_connection('verify_code')
        # 进入函数后, 先获取存储在 redis 中的数据
        send_flag = redis_conn.get('send_flag_%s' % mobile)
        # 查看数据是否存在, 如果存在, 说明60s没过, 返回
        if send_flag:
            return JsonResponse({
                'errno': '4201',
                'errmsg': '非法请求或请求次数受限'
            })

        # 如果过了, 在执行下面的代码:
        # 2. 校验参数
        if not all([mobile, text, id]):
            return JsonResponse({
                'errno': '4103',
                'errmsg': '参数错误'
            })
        # 3. 创建连接到redis的对象
        redis_conn = get_redis_connection('verify_code')

        # 4. 提取图形验证码
        image_code_server = redis_conn.get('img_%s' % id)
        if image_code_server is None:
            # 图形验证码过期或者不存在
            return JsonResponse({
                'errno': '4103',
                'errmsg': '参数错误'
            })

        # 5. 删除图形验证码，避免恶意测试图形验证码
        try:
            redis_conn.delete('img_%s' % id)
        except Exception as e:
            logger.error(e)
        # 6. 对比图形验证码
        # bytes 转字符串
        image_code_server = image_code_server.decode()
        # 转小写后比较
        if text.lower() != image_code_server.lower():
            return JsonResponse({
                'errno': '4103',
                'errmsg': '参数错误'
            })
        # 7. 生成短信验证码：生成6位数验证码
        sms_code = '%06d' % random.randint(0, 999999)
        logger.info(sms_code)

        # 创建管道对象:
        pl = redis_conn.pipeline()

        # redis_conn.setex('sms_%s' % mobile, 300, sms_code)
        pl.setex('sms_%s' % mobile, 300, sms_code)

        # redis_conn.setex('send_flag_%s' % mobile, 60, 1)
        pl.setex('send_flag_%s' % mobile, 60, 1)

        # 执行管道:
        pl.execute()
        ccp_send_sms_code.delay(mobile, sms_code)

        # 10. 响应结果
        return JsonResponse({
            'errno': '0',
            'errmsg': '发送短信成功'
        })

# 注册视图
class RegisterView(View):
    def post(self, request):
        # 1.接收参数
        dict = json.loads(request.body.decode())
        mobile = dict.get('mobile')
        phonecode = dict.get('phonecode')
        password = dict.get('password')
        password2 = dict.get('password2')

        # 2.检验全部参数
        if not all([mobile, phonecode, password, password2]):
            return JsonResponse({
                'errno': '4103',
                'errmsg': '缺少必传参数'
            })
        # 3.mobile检验
        if not re.match(r'^1[3-9]\d{9}$', mobile):
            return JsonResponse({
                'errno': '4103',
                'errmsg': '参数错误'
            })
        # 4.password检验
        if not re.match(r'^[a-zA-Z0-9]{8,20}$', password):
            return JsonResponse({
                'errno': '4103',
                'errmsg': '参数错误'
            })

        # 5.password2 和 password
        if password != password2:
            return JsonResponse({
                'errno': '4103',
                'errmsg': '参数错误'
            })

        # 8.sms_code检验 (链接redis数据库)
        redis_conn = get_redis_connection('verify_code')

        # 9.从redis中取值
        sms_code_server = redis_conn.get('sms_%s' % mobile)

        # 10.判断该值是否存在
        if not sms_code_server:
            return JsonResponse({
                'errno': '4103',
                'errmsg': '参数错误'
            })
        # 11.把redis中取得值和前端发的值对比
        if phonecode != sms_code_server.decode():
            return JsonResponse({
                'errno': '4103',
                'errmsg': '参数错误'
            })
        # 12.保存到数据库 (username password mobile)
        try:
            user = User.objects.create_user(username=mobile,password=password,
                                            mobile=mobile)
        except Exception as e:
            return JsonResponse({
                'errno': '4001',
                'errmsg': '数据库查询错误'
            })

        login(request, user)
        # 生成响应对象
        return JsonResponse({'errno': '0',
                                 'errmsg': 'ok'})

